#pragma once
#include <iostream>
#include <string.h>
#include <jsoncpp/json/json.h>

#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define CRLF "\r\n"
#define CRLF_LEN strlen(CRLF)
#define OPS "+-*/%"

using namespace std;

// 加字符长度
string encode(string &in, int len)
{
    string l = to_string(len);
    string encodein;
    encodein += l;
    encodein += CRLF;
    encodein += in;
    encodein += CRLF;
    return encodein;
}

string decode(string &in, int *len)
{
    *len = 0;
    int CRLFONE = in.find(CRLF, 0);
    if (CRLFONE == string::npos)
    {
        return "";
    }
    string inlen = in.substr(0, CRLFONE);
    int intlen = atoi(inlen.c_str());
    int surplus = in.size() - 2 * CRLF_LEN - CRLFONE;
    if (intlen > surplus)
    {
        return "";
    }
    string packpage = in.substr(CRLFONE + CRLF_LEN, intlen);
    *len = intlen;
    // 完整报文，成功获取数据，从inbuffer中去掉
    int removeLen = inlen.size() + packpage.size() + 2 * CRLF_LEN;
    in.erase(0, removeLen);
    return packpage;
}


class req
{
public:
    void serialize(string *out)
    {
#ifdef MY_SELF
        *out += to_string(x_);
        *out += SPACE;
        *out += to_string(op_);
        *out += SPACE;
        *out += to_string(y_);
#else
        Json::Value root;
        root["x"]=x_;
        root["y"]=y_;
        root["op"]=op_;
        Json::FastWriter fw;
        *out = fw.write(root);
#endif
    }
    bool deserialize(string &in)
    {
#ifdef MY_SELF
        size_t SPACEONE = in.find(SPACE, 0);
        if (SPACEONE == string::npos)
        {
            return false;
        }
        size_t SPACETWO = in.find(SPACE, SPACEONE + 1);
        if (SPACETWO == string::npos)
        {
            return false;
        }
        string x = in.substr(0, SPACEONE);
        string op = in.substr(SPACEONE + 1, 1);
        string y = in.substr(SPACETWO + 1);
        x_ = atoi(x.c_str());
        y_ = atoi(y.c_str());
        op_ = op[0];
        return true;
#else
        Json::Value root;
        Json::Reader rd;
        rd.parse(in,root);
        x_ = root["x"].asInt();
        y_ = root["y"].asInt();
        op_=root["op"].asInt();
        return true;
#endif
    }

public:
    int x_;
    int y_;
    char op_;
};

class resp
{
public:
    void serialize(string *out)
    {
#ifdef MY_SELF
        *out += to_string(result_);
        *out += SPACE;
        *out += to_string(errcode_);
#else
        Json::Value root;
        Json::FastWriter fw;
        root["result"]=result_;
        root["errcode"]=errcode_;
        *out = fw.write(root);
#endif
    }

    bool deserialize(string &in)
    {
#ifdef MY_SELF
        size_t SPACEONE = in.find(SPACE, 0);
        if (SPACEONE == string::npos)
        {
            return false;
        }
        string result = in.substr(0, SPACEONE);
        string errcode = in.substr(SPACEONE + 1);
        result_ = atoi(result.c_str());
        errcode_ = atoi(errcode.c_str());
#else
        Json::Value root;
        Json::Reader rd;
        rd.parse(in,root);
        errcode_ = root["errcode"].asInt();
        result_ = root["result"].asInt();
        return true;
#endif
    }

public:
    int result_;
    int errcode_;
};

bool makeReuquest(const std::string &str, req *req)
{
    // 123+1  1*1 1/1
    char strtmp[1024];
    snprintf(strtmp, sizeof strtmp, "%s", str.c_str());
    char *left = strtok(strtmp, OPS);
    if (!left)
        return false;
    char *right = strtok(nullptr, OPS);
    if (!right)
        return false;
    char mid = str[strlen(left)];

    req->x_ = atoi(left);
    req->y_ = atoi(right);
    req->op_ = mid;
    return true;
}